home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
9-Digit Zip Code Directory
/
9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO
/
z4src.zip
/
DIAPPEND.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-16
|
10KB
|
311 lines
//----------------------------------------------------------------------------
// MODULE DESCRIPTION
//
// Module: diappend.c
// Title: Data File I/O Library
// Notice: John M. Weeder
// Copyright (c) 1993. All rights reserved.
// This module contains proprietary information and should be
// treated as confidential.
//
//----------------------------------------------------------------------------
// MAINTENANCE HISTORY
//
// $Workfile$
// $Revision$
// $Author$
// $Date$
// $Log$
//
//----------------------------------------------------------------------------
// MODULE NARRATIVE
//
//
// This module contains to append data to a data file. There are two
// approaches:
// DioAppend() appends an entire file.
// or
// DioAppendNewEntry() and DioAppendUpdate()
//
// DioAppendNewEntry() returns a file handle which can be written to.
// DioAppendUpdate() updates the directory entry when the user is finished
// writing to the file.
//
// The code in this module should be written entirely in C.
// Do not use any C++ constructs.
//
// This module is portable to:
// DOS 3.X+
// MS Windows 3.X+
// OS/2 2.X+
// OS/2 2.0 PM
// SCO UNIX.
//
// The following compilers are supported:
// MSC 6.0A
// MSC/C++ 7.0
// Borland C++ 3.1 for DOS
// Borland C++ 1.0 for OS/2 2.X
// SCO UNIX cc
//
//----------------------------------------------------------------------------
#include <di.h>
//----------------------------------------------------------------------------
// Global
//----------------------------------------------------------------------------
typedef struct GA // Global data
{
HPF hpf; // Physical file handle
SIZET cDir; // Offset of directory entry
DATAHDR hdr; // Header data for physical file
DATADIR dir; // Directory entry data
BOOL fUser; // User physical file?
} GA;
static GA ga;
//----------------------------------------------------------------------------
// Description: Create a new data file entry and return a handle to allow
// appending to the file.
// Parameters: pcsz Physical file name.
// If upper 2 byte are zero, the lower 2 bytes
// specify the physical file handle
// pcszName Logical file name.
// usType Logical file type.
// usBlock Block size. 0 if file is not blocked.
// phf Variable to receive file handle to write to.
// pfAppend If not null, points to a boolean variable
// specifying whether to append to an existing file.
// If null, file is not appended!
// If true, append to existing file. Otherwise,
// create.
// Returns TRUE if appending.
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_E DioAppend(PCSZ pcsz, PCSZ pcszName, USHORT usType, USHORT usBlockSize, PHF phf, PBOOL pfAppend)
{
FPOS fsize;
HPF hpfFind;
BOOL fAppend = pfAppend ? *pfAppend: FALSE;
Assert(usBlockSize <= MAX_BLOCK_SIZE);
memset(&ga, 0, sizeof(ga)); // Clear globals
*phf = -1; // Initialize file handle
if (HIUSHORT(pcsz))
{
if (!DioOpenPhysical(pcsz, &ga.hpf, TRUE))
return FALSE;
ga.fUser = FALSE;
}
else
{
ga.hpf = LOUSHORT(pcsz);
Assert(ga.hpf >= 0 && ga.hpf < MAX_PHYSICAL_FILES);
Assert(di.physical[ga.hpf].fUsed);
ga.fUser = TRUE;
}
// Delete existing file
if (DioFindLogical(pcszName, usType, &hpfFind, &ga.cDir, &ga.dir)
&& hpfFind == ga.hpf)
{
if (fAppend) // Continue appending!!
{
fsize = FileGetSize(di.physical[ga.hpf].hf);
if (fsize < 0)
{
di.physical[ga.hpf].fl |= PF_ERROR;
return FALSE;
}
if (!DioHeaderRead(ga.hpf, &ga.hdr))
return FALSE;
if (!FileSetPos(di.physical[ga.hpf].hf, fsize, FL_BEGIN))
{
di.physical[ga.hpf].fl |= PF_ERROR;
return FALSE;
} // Must be last entry in file!
Assert(ga.cDir == ga.hdr.usDirectoryUsed - 1);
*phf = di.physical[ga.hpf].hf;
if (pfAppend)
*pfAppend = TRUE;
return TRUE;
}
else
{
if (!DioDelete(HPF2PCSZ(ga.hpf), pcszName, usType))
return FALSE;
}
}
if (pfAppend)
*pfAppend = FALSE;
if (!DioHeaderRead(ga.hpf, &ga.hdr))
return FALSE;
if (ga.hdr.usDirectoryUsed >= ga.hdr.usDirectoryEntries)
{
Error("Physical file directory table is full.");
return FALSE;
}
fsize = FileGetSize(di.physical[ga.hpf].hf);
if (fsize < 0)
{
di.physical[ga.hpf].fl |= PF_ERROR;
return FALSE;
}
if ((fsize % DFH_SIZE) != 0)
{
di.physical[ga.hpf].fl |= PF_ERROR;
Error("Data file has invalid size.");
return FALSE;
}
ga.cDir = ga.hdr.usDirectoryUsed;
if (usType == DFT_RANDOM)
usBlockSize = 0;
Assert(pcszName && pcszName[0] && strlen(pcszName) <= DFD_NAME);
Assert(usType < DFT_MAX);
Assert(usType == DFT_RANDOM || usBlockSize > 0);
Assert(phf);
memset(&ga.dir, 0, sizeof(ga.dir));
memcpy(ga.dir.chName, pcszName, MIN(DFD_NAME, strlen(pcszName)));
ga.dir.usType = usType;
ga.dir.usBlockSize = usBlockSize;
ga.dir.fbase = fsize;
if (!FileSetPos(di.physical[ga.hpf].hf, fsize, FL_BEGIN))
{
di.physical[ga.hpf].fl |= PF_ERROR;
return FALSE;
}
*phf = di.physical[ga.hpf].hf;
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Update a data file after appending data.
// Parameters: fSuccess If true, append succeeded, else it failed!
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_E DioAppendClose(BOOL fSuccess, BOOL fCrc)
{
FPOS fsize;
BYTE bBuf[DFH_SIZE];
BOOL fResult = FALSE;
// If failure, close and exit
if (!fSuccess || (di.physical[ga.hpf].fl & PF_ERROR))
goto ERROR_EXIT;
// Get new file size
fsize = FileGetSize(di.physical[ga.hpf].hf);
if (fsize < 0)
goto ERROR_EXIT;
ga.dir.flen = fsize - ga.dir.fbase; // Calculate length of file
if (!ga.dir.flen) // Must be > 0
{
Error("Logical file is empty!");
goto ERROR_EXIT;
}
if (ga.dir.usBlockSize) // If blocked, verify full blocks
{ // were written
if ((ga.dir.flen % (FPOS)ga.dir.usBlockSize) != 0)
{
Error("Invalid file size.\nPartial block written.");
goto ERROR_EXIT;
}
}
else if ((ga.dir.flen % (FPOS)DFH_SIZE) != 0)
{ // Round to multiple of header size
SIZET cBuf = (SIZET)(DFH_SIZE - (SIZET)(ga.dir.flen % DFH_SIZE));
memset(bBuf, 0, cBuf);
if (!FileWrite(di.physical[ga.hpf].hf, bBuf, cBuf, fsize))
goto ERROR_EXIT;
}
if (fCrc) // Calculate CRC of data area
if (!FileCrc(di.physical[ga.hpf].hf, &ga.dir.crcData, ga.dir.flen, ga.dir.fbase))
goto ERROR_EXIT;
// Update directory entry
if (!DioDirWrite(ga.hpf, ga.cDir, &ga.dir))
goto ERROR_EXIT;
// Update header
if (ga.cDir >= ga.hdr.usDirectoryUsed)
ga.hdr.usDirectoryUsed++;
if (!DioHeaderWrite(ga.hpf, &ga.hdr))
goto ERROR_EXIT;
if (!DioFlush()) // Flush file
goto ERROR_EXIT;
fResult = TRUE;
ERROR_EXIT:
if (!ga.fUser) // If not a user file, close it
if (!DioClosePhysical(ga.hpf))
fResult = FALSE;
return fResult;
}
//----------------------------------------------------------------------------
// Description: Append an external binary file to a data file.
// Parameters: pcsz Physical file name.
// File is opened, then closed when updating is
// complete.
// pcszName Logical file name.
// usType Logical file type.
// usBlockSize Block size. 0 if file is not blocked.
// pcszFile File name to append.
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_E DioAppendFile(PCSZ pcsz, PCSZ pcszName, USHORT usType, USHORT usBlockSize, PCSZ pcszFile)
{
FLAG16 fs = FL_OPEN|FL_READONLY|FL_DENYREADWRITE|FL_BINARY;
HF hf1, hf2 = -1;
FPOS fsize;
BOOL fResult = FALSE;
BYTE bBuf[sizeof(DATAHDR)];
SIZET cExtra = 0;
// Get handle to write to
Assert(usBlockSize <= MAX_BLOCK_SIZE);
usBlockSize = usBlockSize ? usBlockSize: (8 _K);
if (!DioAppend(pcsz, pcszName, usType, usBlockSize, &hf1, NULL))
return FALSE;
// Open external file
if (!FileOpen(&hf2, pcszFile, fs, NULL))
return FALSE;
fsize = FileGetSize(hf2); // Get size of external file
if (!FileSetPos(hf2, 0, FL_BEGIN))
goto ERROR_EXIT;
if ((fsize % (FPOS)sizeof(DATAHDR)) != 0)
cExtra = sizeof(DATAHDR) - (SIZET)(fsize % (FPOS)sizeof(DATAHDR));
if (!FileCopy(hf1, -1, hf2, 0, fsize))
goto ERROR_EXIT;
if (cExtra) // Round to correct multiple if needed!
{
memset(bBuf, 0, cExtra);
if (!FileWrite(hf1, bBuf, cExtra, -1))
goto ERROR_EXIT;
}
fResult = TRUE;
ERROR_EXIT:
if (hf2 >= 0)
FileClose(hf2);
if (!DioAppendClose(fResult, TRUE))
fResult = FALSE;
return fResult;
}
//----------------------------------------------------------------------------
//------------------------------- End of File --------------------------------
//----------------------------------------------------------------------------